﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections;
using System.Reflection;
using System.Windows.Input;
using Utils;

namespace BuildPreparation
{
    public static class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            var task = new BuildPreparationTask();

            task.BuildEngine = new BuildProxy();
            task.HostObject = (ITaskHost) task.BuildEngine;

            task.Execute();
        }
    }

    public class BuildPreparationTask : ITask
    {
        public IBuildEngine BuildEngine { get; set; }
        public ITaskHost HostObject { get; set; }

        [STAThread]
        public bool Execute()
        {
            try
            {
                if (Key.LeftShift.IsPressed())
                {
                    return true;
                }

                var projectFile = new FileInfo(this.BuildEngine.ProjectFileOfTaskNode);
                var solutionPath = projectFile.Directory.Parent.FullName;
                var zipAssemblyFile = new FileInfo(Path.Combine(solutionPath, @"Binaries\ICSharpCode.SharpZipLib.dll"));
                var dotNetFxFolder = (string)null;
                var sdkFolder = (string)null;
                var silverlightPath = (string)null;
                var vsSP1Path = (string)null;
                var vsCommon = (string)null;
                var message = new BuildMessageEventArgs("Prepping build.. please wait", "", "", MessageImportance.High);

                this.BuildEngine.LogMessageEvent(message);

                zipAssemblyFile.Attributes &= (~FileAttributes.ReadOnly);

                if (Environment.Is64BitOperatingSystem)
                {
                    sdkFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Microsoft SDKs");
                    silverlightPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Microsoft Silverlight\5.1.10411.0");
                    vsSP1Path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Microsoft Visual Studio 2010 SDK SP1");
                    vsCommon = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Microsoft Visual Studio 10.0\Common7");
                    dotNetFxFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"Microsoft.NET\Framework64\v4.0.30319");
                }
                else
                {
                    sdkFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft SDKs");
                    silverlightPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft Silverlight\5.1.10411.0");
                    vsSP1Path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft Visual Studio 2010 SDK SP1");
                    vsCommon = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft Visual Studio 10.0\Common7");
                    dotNetFxFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"Microsoft.NET\Framework\v4.0.30319");
                }

                var zipAssemblyExisting = new FileInfo(Path.Combine(dotNetFxFolder, zipAssemblyFile.Name));

                if (!zipAssemblyExisting.Exists)
                {
                    // copy so that other tasks can find its references

                    File.Copy(zipAssemblyFile.FullName, zipAssemblyExisting.FullName);
                }

                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("SFSOLUTIONPATH")))
                {
                    Environment.SetEnvironmentVariable("SFSOLUTIONPATH", solutionPath, EnvironmentVariableTarget.Machine);
                }

                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("SDKPATH")))
                {
                    Environment.SetEnvironmentVariable("SDKPATH", sdkFolder, EnvironmentVariableTarget.Machine);
                }

                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("SILVERLIGHTPATH")))
                {
                    Environment.SetEnvironmentVariable("SILVERLIGHTPATH", silverlightPath, EnvironmentVariableTarget.Machine);
                }

                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("VSSP1PATH")))
                {
                    Environment.SetEnvironmentVariable("VSSP1PATH", vsSP1Path, EnvironmentVariableTarget.Machine);
                }

                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("VSCOMMON")))
                {
                    Environment.SetEnvironmentVariable("VSCOMMON", vsCommon, EnvironmentVariableTarget.Machine);
                }

                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("FrameworkDir")))
                {
                    Environment.SetEnvironmentVariable("FrameworkDir", dotNetFxFolder, EnvironmentVariableTarget.Machine);
                }

                var process = Process.Start(Path.Combine(solutionPath, @"Binaries\BuildSweeper\BuildSweeper.exe"), "\"" + solutionPath + "\"");

                process.WaitForExit();
            }
            catch (Exception ex)
            {
                var message = new BuildErrorEventArgs(string.Empty, string.Empty, string.Empty, 0, 0, 0, 0, "Error prepping build.  Read ReadMe.txt in Document folder", "", "", DateTime.Now);

                this.BuildEngine.LogErrorEvent(message);

                Console.WriteLine(string.Format("Error prepping build: '{0}'", ex.Message));
                Console.WriteLine("You may need to run Visual Studio in Administrator mode at least once to add environment variables.");
                Console.WriteLine("Press any key to continue.");

                Console.Read();

                return false;
            }

            return true;
        }
    }

    public class BuildProxy : IBuildEngine, ITaskHost
    {
        public bool BuildProjectFile(string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs)
        {
            throw new NotImplementedException();
        }

        public string ProjectFileOfTaskNode
        {
            get
            {
                var assembly = Assembly.GetExecutingAssembly();
                var directory = new DirectoryInfo(Path.GetFullPath(Path.Combine(new FileInfo(assembly.Location).DirectoryName, @"..\..\")));
                var file = directory.GetFiles("*.csproj").First();

                return file.FullName;
            }
        }

        public int ColumnNumberOfTaskNode
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public bool ContinueOnError
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public int LineNumberOfTaskNode
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public void LogCustomEvent(CustomBuildEventArgs e)
        {
            Console.WriteLine(e.Message);
        }

        public void LogErrorEvent(BuildErrorEventArgs e)
        {
            Console.WriteLine(e.Message);
        }

        public void LogMessageEvent(BuildMessageEventArgs e)
        {
            Console.WriteLine(e.Message);
        }

        public void LogWarningEvent(BuildWarningEventArgs e)
        {
            Console.WriteLine(e.Message);
        }
    }
}
